Implement source redirection
authorAlex Crichton <alex@alexcrichton.com>
Wed, 3 Feb 2016 18:54:07 +0000 (10:54 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 1 Aug 2016 17:14:52 +0000 (10:14 -0700)
This commit implements a scheme for .cargo/config files where sources can be
redirected to other sources. The purpose of this will be to override crates.io
for a few use cases:

  * Replace it with a mirror site that is sync'd to crates.io
  * Replace it with a "directory source" or some other local source

This major feature of this redirection, however, is that none of it is encoded
into the lock file. If one source is redirected to another then it is assumed
that packages from both are exactly the same (e.g. `foo v0.0.1` is the same in
both location). The lock file simply encodes the canonical soure (e.g.
crates.io) rather than the replacement source. In the end this means that
Cargo.lock files can be generated from any replacement source and shipped to
other locations without the lockfile oscillating about where packages came from.

Eventually this support will be extended to `Cargo.toml` itself (which will be
encoded into the lock file), but that support is not implemented today. The
syntax for what was implemented today looks like:

    # .cargo/config
    [source.my-awesome-registry]
    registry = 'https://example.com/path/to/index'

    [source.crates-io]
    replace-with = 'my-awesome-registry'

Each source will have a canonical name and will be configured with the various
keys underneath it (today just 'registry' and 'directory' will be accepted). The
global `crates-io` source represents crates from the standard registry, and this
can be replaced with other mirror sources.

All tests have been modified to use this new infrastructure instead of the old
`registry.index` configuration. This configuration is now also deprecated and
will emit an unconditional warning about how it will no longer be used in the
future.

Finally, all subcommands now use this "source map" except for `cargo publish`,
which will always publish to the default registry (in this case crates.io).

29 files changed:
src/bin/install.rs
src/bin/login.rs
src/cargo/core/package_id.rs
src/cargo/core/registry.rs
src/cargo/core/source.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_fetch.rs
src/cargo/ops/cargo_generate_lockfile.rs
src/cargo/ops/cargo_install.rs
src/cargo/ops/cargo_package.rs
src/cargo/ops/registry.rs
src/cargo/sources/config.rs [new file with mode: 0644]
src/cargo/sources/mod.rs
src/cargo/sources/registry.rs
src/cargo/sources/replaced.rs [new file with mode: 0644]
src/cargo/util/config.rs
src/cargo/util/toml.rs
tests/bad-config.rs
tests/build-script.rs
tests/cargo_alias_config.rs
tests/cargotest/support/registry.rs
tests/install.rs
tests/metadata.rs
tests/overrides.rs
tests/publish.rs
tests/registry.rs
tests/search.rs
tests/workspaces.rs

index e7d3d03f7b0ad44552074e4d5048e6eeb21195cb..2a58688021dc7f52e4b4d10727aa52b35c5da4ef 100644 (file)
@@ -132,7 +132,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
     } else if options.arg_crate == None {
         try!(SourceId::for_path(&config.cwd()))
     } else {
-        try!(SourceId::for_central(config))
+        try!(SourceId::crates_io(config))
     };
 
     let krate = options.arg_crate.as_ref().map(|s| &s[..]);
index 635321c578d34162ff77636730d98695210f0cf0..a732c65faa4615f54752ed32b983647ab538f8d2 100644 (file)
@@ -43,7 +43,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
     let token = match options.arg_token.clone() {
         Some(token) => token,
         None => {
-            let src = try!(SourceId::for_central(config));
+            let src = try!(SourceId::crates_io(config));
             let mut src = RegistrySource::new(&src, config);
             try!(src.update());
             let config = try!(src.config());
index 7d24bbe0e8bcf5f3aab585de60cad0a6206c6b81..b29b8ca11d5ee5d8d6d1c3848a4a07fa7b030fd4 100644 (file)
@@ -203,12 +203,12 @@ impl fmt::Debug for PackageId {
 mod tests {
     use super::PackageId;
     use core::source::SourceId;
-    use sources::RegistrySource;
+    use sources::CRATES_IO;
     use util::ToUrl;
 
     #[test]
     fn invalid_version_handled_nicely() {
-        let loc = RegistrySource::default_url().to_url().unwrap();
+        let loc = CRATES_IO.to_url().unwrap();
         let repo = SourceId::for_registry(&loc);
 
         assert!(PackageId::new("foo", "1.0", &repo).is_err());
index 6dc2d9cc4ddfb53b76a8c993d911add566012cd3..6e7d1bf8f958b1fccfb61b4cc4e3f286e22b14a6 100644 (file)
@@ -3,6 +3,7 @@ use std::collections::{HashSet, HashMap};
 use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId, Package};
 use core::PackageSet;
 use util::{CargoResult, ChainError, Config, human, profile};
+use sources::config::SourceConfigMap;
 
 /// Source of information about a group of packages.
 ///
@@ -47,7 +48,6 @@ impl<'a, T: ?Sized + Registry + 'a> Registry for Box<T> {
 /// operations if necessary) and is ready to be queried for packages.
 pub struct PackageRegistry<'cfg> {
     sources: SourceMap<'cfg>,
-    config: &'cfg Config,
 
     // A list of sources which are considered "overrides" which take precedent
     // when querying for packages.
@@ -71,6 +71,7 @@ pub struct PackageRegistry<'cfg> {
     source_ids: HashMap<SourceId, (SourceId, Kind)>,
 
     locked: HashMap<SourceId, HashMap<String, Vec<(PackageId, Vec<PackageId>)>>>,
+    source_config: SourceConfigMap<'cfg>,
 }
 
 #[derive(PartialEq, Eq, Clone, Copy)]
@@ -81,14 +82,15 @@ enum Kind {
 }
 
 impl<'cfg> PackageRegistry<'cfg> {
-    pub fn new(config: &'cfg Config) -> PackageRegistry<'cfg> {
-        PackageRegistry {
+    pub fn new(config: &'cfg Config) -> CargoResult<PackageRegistry<'cfg>> {
+        let source_config = try!(SourceConfigMap::new(config));
+        Ok(PackageRegistry {
             sources: SourceMap::new(),
             source_ids: HashMap::new(),
             overrides: Vec::new(),
-            config: config,
+            source_config: source_config,
             locked: HashMap::new(),
-        }
+        })
     }
 
     pub fn get(self, package_ids: &[PackageId]) -> PackageSet<'cfg> {
@@ -164,8 +166,8 @@ impl<'cfg> PackageRegistry<'cfg> {
 
     fn load(&mut self, source_id: &SourceId, kind: Kind) -> CargoResult<()> {
         (|| {
-            // Save off the source
-            let source = source_id.load(self.config);
+            let source = try!(self.source_config.load(source_id));
+
             if kind == Kind::Override {
                 self.overrides.push(source_id.clone());
             }
index e590f661b7d56810f017030449c6f823fb26ae79..2b5dc1347b757454aeb59ae362fa8f30095a8bd8 100644 (file)
@@ -4,13 +4,16 @@ use std::fmt::{self, Formatter};
 use std::hash;
 use std::path::Path;
 use std::sync::Arc;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
+use std::sync::atomic::Ordering::SeqCst;
 
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use url::Url;
 
 use core::{Package, PackageId, Registry};
-use sources::{PathSource, GitSource, RegistrySource};
+use ops;
 use sources::git;
+use sources::{PathSource, GitSource, RegistrySource, CRATES_IO};
 use util::{human, Config, CargoResult, ToUrl};
 
 /// A Source finds and downloads remote packages based on names and
@@ -185,8 +188,22 @@ impl SourceId {
     ///
     /// This is the main cargo registry by default, but it can be overridden in
     /// a `.cargo/config`.
-    pub fn for_central(config: &Config) -> CargoResult<SourceId> {
-        Ok(SourceId::for_registry(&try!(RegistrySource::url(config))))
+    pub fn crates_io(config: &Config) -> CargoResult<SourceId> {
+        let cfg = try!(ops::registry_configuration(config));
+        let url = if let Some(ref index) = cfg.index {
+            static WARNED: AtomicBool = ATOMIC_BOOL_INIT;
+            if !WARNED.swap(true, SeqCst) {
+                try!(config.shell().warn("custom registry support via \
+                                          the `registry.index` configuration is \
+                                          being removed, this functionality \
+                                          will not work in the future"));
+            }
+            &index[..]
+        } else {
+            CRATES_IO
+        };
+        let url = try!(url.to_url());
+        Ok(SourceId::for_registry(&url))
     }
 
     pub fn url(&self) -> &Url {
@@ -247,7 +264,7 @@ impl SourceId {
             Kind::Registry => {}
             _ => return false,
         }
-        self.inner.url.to_string() == RegistrySource::default_url()
+        self.inner.url.to_string() == CRATES_IO
     }
 }
 
index 21cb053d12cd25b0e357b37d6a4a3e979ada515c..e19b37f116fc20ecd09930d532adc9b6382c15e5 100644 (file)
@@ -28,7 +28,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
         return rm_rf(&target_dir);
     }
 
-    let mut registry = PackageRegistry::new(opts.config);
+    let mut registry = try!(PackageRegistry::new(opts.config));
     let resolve = try!(ops::resolve_ws(&mut registry, ws));
     let packages = ops::get_resolved_packages(&resolve, registry);
 
index 78d16365c53867810c532246482b33d8d3019d50..3ea700f49afd646d839231fafb0df9c264d95d51 100644 (file)
@@ -97,7 +97,7 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>,
                                 no_default_features: bool)
                                 -> CargoResult<(PackageSet<'a>, Resolve)> {
 
-    let mut registry = PackageRegistry::new(ws.config());
+    let mut registry = try!(PackageRegistry::new(ws.config()));
 
     if let Some(source) = source {
         registry.add_preloaded(try!(ws.current()).package_id().source_id(),
@@ -389,6 +389,7 @@ fn add_overrides<'a>(registry: &mut PackageRegistry<'a>,
         None => return Ok(())
     };
     let current = try!(ws.current());
+
     let paths = paths.val.iter().map(|&(ref s, ref p)| {
         // The path listed next to the string is the config file in which the
         // key was located, so we want to pop off the `.cargo/config` component
@@ -482,11 +483,11 @@ fn scrape_target_config(config: &Config, triple: &str)
             rerun_if_changed: Vec::new(),
             warnings: Vec::new(),
         };
-        for (k, value) in try!(value.table()).0 {
+        for (k, value) in try!(value.table(&lib_name)).0 {
             let key = format!("{}.{}", key, k);
             match &k[..] {
                 "rustc-flags" => {
-                    let (flags, definition) = try!(value.string());
+                    let (flags, definition) = try!(value.string(&k));
                     let whence = format!("in `{}` (in {})", key,
                                          definition.display());
                     let (paths, links) = try!(
@@ -496,22 +497,22 @@ fn scrape_target_config(config: &Config, triple: &str)
                     output.library_links.extend(links);
                 }
                 "rustc-link-lib" => {
-                    let list = try!(value.list());
+                    let list = try!(value.list(&k));
                     output.library_links.extend(list.iter()
                                                     .map(|v| v.0.clone()));
                 }
                 "rustc-link-search" => {
-                    let list = try!(value.list());
+                    let list = try!(value.list(&k));
                     output.library_paths.extend(list.iter().map(|v| {
                         PathBuf::from(&v.0)
                     }));
                 }
                 "rustc-cfg" => {
-                    let list = try!(value.list());
+                    let list = try!(value.list(&k));
                     output.cfgs.extend(list.iter().map(|v| v.0.clone()));
                 }
                 _ => {
-                    let val = try!(value.string()).0;
+                    let val = try!(value.string(&k)).0;
                     output.metadata.push((k.clone(), val.to_string()));
                 }
             }
index 03b19ca5d19c5e8e59a686746f2a90187a9ca3fd..a0144c8f4729c3f2758821bbdc30d6bf0ffd37da 100644 (file)
@@ -5,7 +5,7 @@ use util::CargoResult;
 
 /// Executes `cargo fetch`.
 pub fn fetch<'a>(ws: &Workspace<'a>) -> CargoResult<(Resolve, PackageSet<'a>)> {
-    let mut registry = PackageRegistry::new(ws.config());
+    let mut registry = try!(PackageRegistry::new(ws.config()));
     let resolve = try!(ops::resolve_ws(&mut registry, ws));
     let packages = get_resolved_packages(&resolve, registry);
     for id in resolve.iter() {
index b196dec916bd7a983c42236950355e0875d05127..45ee2b10111b7a6ed9618a77ce18099c232c8a81 100644 (file)
@@ -16,7 +16,7 @@ pub struct UpdateOptions<'a> {
 }
 
 pub fn generate_lockfile(ws: &Workspace) -> CargoResult<()> {
-    let mut registry = PackageRegistry::new(ws.config());
+    let mut registry = try!(PackageRegistry::new(ws.config()));
     let resolve = try!(ops::resolve_with_previous(&mut registry, ws,
                                                   Method::Everything,
                                                   None, None));
@@ -35,7 +35,7 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
         Some(resolve) => resolve,
         None => return generate_lockfile(ws),
     };
-    let mut registry = PackageRegistry::new(opts.config);
+    let mut registry = try!(PackageRegistry::new(opts.config));
     let mut to_avoid = HashSet::new();
 
     if opts.to_update.is_empty() {
index b120ace95e19de96985cdb283ebe6c7426c4580f..d25bf11ba180ec696584fc52fe401c69c3e61745 100644 (file)
@@ -13,7 +13,7 @@ use toml;
 use core::{SourceId, Source, Package, Dependency, PackageIdSpec};
 use core::{PackageId, Workspace};
 use ops::{self, CompileFilter};
-use sources::{GitSource, PathSource, RegistrySource};
+use sources::{GitSource, PathSource, SourceConfigMap};
 use util::{CargoResult, ChainError, Config, human, internal};
 use util::{Filesystem, FileLock};
 
@@ -54,6 +54,7 @@ pub fn install(root: Option<&str>,
                force: bool) -> CargoResult<()> {
     let config = opts.config;
     let root = try!(resolve_root(root, config));
+    let map = try!(SourceConfigMap::new(config));
     let (pkg, source) = if source_id.is_git() {
         try!(select_pkg(GitSource::new(source_id, config), source_id,
                         krate, vers, &mut |git| git.read_packages()))
@@ -70,7 +71,7 @@ pub fn install(root: Option<&str>,
                         source_id, krate, vers,
                         &mut |path| path.read_packages()))
     } else {
-        try!(select_pkg(RegistrySource::new(source_id, config),
+        try!(select_pkg(try!(map.load(source_id)),
                         source_id, krate, vers,
                         &mut |_| Err(human("must specify a crate to install from \
                                             crates.io, or use --path or --git to \
index 4e6ae0a9d71b27b3449754213dd0b616d19f30b4..e6a89e331b072b6d4a19876723b73789cbf4a2b1 100644 (file)
@@ -247,21 +247,21 @@ fn run_verify(ws: &Workspace, tar: &File, opts: &PackageOpts) -> CargoResult<()>
     try!(archive.unpack(dst.parent().unwrap()));
     let manifest_path = dst.join("Cargo.toml");
 
-    // When packages are uploaded to the registry, all path dependencies are
-    // implicitly converted to registry-based dependencies, so we rewrite those
+    // When packages are uploaded to a registry, all path dependencies are
+    // implicitly converted to registry dependencies, so we rewrite those
     // dependencies here.
     //
     // We also make sure to point all paths at `dst` instead of the previous
     // location that the package was originally read from. In locking the
     // `SourceId` we're telling it that the corresponding `PathSource` will be
     // considered updated and we won't actually read any packages.
-    let registry = try!(SourceId::for_central(config));
+    let cratesio = try!(SourceId::crates_io(config));
     let precise = Some("locked".to_string());
     let new_src = try!(SourceId::for_path(&dst)).with_precise(precise);
     let new_pkgid = try!(PackageId::new(pkg.name(), pkg.version(), &new_src));
     let new_summary = pkg.summary().clone().map_dependencies(|d| {
         if !d.source_id().is_path() { return d }
-        d.clone_inner().set_source_id(registry.clone()).into_dependency()
+        d.clone_inner().set_source_id(cratesio.clone()).into_dependency()
     });
     let mut new_manifest = pkg.manifest().clone();
     new_manifest.set_summary(new_summary.override_id(new_pkgid));
index e47b0f7a2c05519fb09f280f01283d6b43383faa..20ad7fcd9be799a67678ecc080113a65ba395b4d 100644 (file)
@@ -163,16 +163,17 @@ pub fn registry(config: &Config,
     // Parse all configuration options
     let RegistryConfig {
         token: token_config,
-        index: index_config,
+        index: _index_config,
     } = try!(registry_configuration(config));
     let token = token.or(token_config);
-    let index = index.or(index_config).unwrap_or(RegistrySource::default_url());
-    let index = try!(index.to_url());
-    let sid = SourceId::for_registry(&index);
+    let sid = match index {
+        Some(index) => SourceId::for_registry(&try!(index.to_url())),
+        None => try!(SourceId::crates_io(config)),
+    };
     let api_host = {
         let mut src = RegistrySource::new(&sid, config);
         try!(src.update().chain_error(|| {
-            human(format!("failed to update registry {}", index))
+            human(format!("failed to update {}", sid))
         }));
         (try!(src.config())).api
     };
diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs
new file mode 100644 (file)
index 0000000..b0e88f1
--- /dev/null
@@ -0,0 +1,149 @@
+//! Implementation of configuration for various sources
+//!
+//! This module will parse the various `source.*` TOML configuration keys into a
+//! structure usable by Cargo itself. Currently this is primarily used to map
+//! sources to one another via the `replace-with` key in `.cargo/config`.
+
+use std::collections::HashMap;
+use std::path::{Path, PathBuf};
+
+use url::Url;
+
+use core::{Source, SourceId};
+use sources::ReplacedSource;
+use util::{CargoResult, Config, ChainError, human, ToUrl};
+use util::config::ConfigValue;
+
+pub struct SourceConfigMap<'cfg> {
+    cfgs: HashMap<String, SourceConfig>,
+    id2name: HashMap<SourceId, String>,
+    config: &'cfg Config,
+}
+
+/// Configuration for a particular source, found in TOML looking like:
+///
+/// ```toml
+/// [source.crates-io]
+/// registry = 'https://github.com/rust-lang/crates.io-index'
+/// replace-with = 'foo'    # optional
+/// ```
+struct SourceConfig {
+    // id this source corresponds to, inferred from the various defined keys in
+    // the configuration
+    id: SourceId,
+
+    // Name of the source that this source should be replaced with. This field
+    // is a tuple of (name, path) where path is where this configuration key was
+    // defined (the literal `.cargo/config` file).
+    replace_with: Option<(String, PathBuf)>,
+}
+
+impl<'cfg> SourceConfigMap<'cfg> {
+    pub fn new(config: &'cfg Config) -> CargoResult<SourceConfigMap<'cfg>> {
+        let mut base = try!(SourceConfigMap::empty(config));
+        if let Some(table) = try!(config.get_table("source")) {
+            for (key, value) in table.val.iter() {
+                try!(base.add_config(key, value));
+            }
+        }
+        Ok(base)
+    }
+
+    pub fn empty(config: &'cfg Config) -> CargoResult<SourceConfigMap<'cfg>> {
+        let mut base = SourceConfigMap {
+            cfgs: HashMap::new(),
+            id2name: HashMap::new(),
+            config: config,
+        };
+        base.add("crates-io", SourceConfig {
+            id: try!(SourceId::crates_io(config)),
+            replace_with: None,
+        });
+        Ok(base)
+    }
+
+    pub fn load(&self, id: &SourceId) -> CargoResult<Box<Source + 'cfg>> {
+        debug!("loading: {}", id);
+        let mut name = match self.id2name.get(id) {
+            Some(name) => name,
+            None => return Ok(id.load(self.config)),
+        };
+        let mut path = Path::new("/");
+        let orig_name = name;
+        loop {
+            let cfg = match self.cfgs.get(name) {
+                Some(cfg) => cfg,
+                None => bail!("could not find a configured source with the \
+                               name `{}` when attempting to lookup `{}` \
+                               (configuration in `{}`)",
+                              name, orig_name, path.display()),
+            };
+            match cfg.replace_with {
+                Some((ref s, ref p)) => {
+                    name = s;
+                    path = p;
+                }
+                None if *id == cfg.id => return Ok(id.load(self.config)),
+                None => {
+                    let new_id = cfg.id.with_precise(id.precise()
+                                                       .map(|s| s.to_string()));
+                    let src = new_id.load(self.config);
+                    return Ok(Box::new(ReplacedSource::new(id, &new_id, src)))
+                }
+            }
+            debug!("following pointer to {}", name);
+            if name == orig_name {
+                bail!("detected a cycle of `replace-with` sources, the source \
+                       `{}` is eventually replaced with itself \
+                       (configuration in `{}`)", name, path.display())
+            }
+        }
+    }
+
+    fn add(&mut self, name: &str, cfg: SourceConfig) {
+        self.id2name.insert(cfg.id.clone(), name.to_string());
+        self.cfgs.insert(name.to_string(), cfg);
+    }
+
+    fn add_config(&mut self, name: &str, cfg: &ConfigValue) -> CargoResult<()> {
+        let (table, _path) = try!(cfg.table(&format!("source.{}", name)));
+        let mut srcs = Vec::new();
+        if let Some(val) = table.get("registry") {
+            let url = try!(url(val, &format!("source.{}.registry", name)));
+            srcs.push(SourceId::for_registry(&url));
+        }
+
+        let mut srcs = srcs.into_iter();
+        let src = try!(srcs.next().chain_error(|| {
+            human(format!("no source URL specified for `source.{}`, needs \
+                           `registry` defined", name))
+        }));
+        if srcs.next().is_some() {
+            return Err(human(format!("more than one source URL specified for \
+                                      `source.{}`", name)))
+        }
+
+        let mut replace_with = None;
+        if let Some(val) = table.get("replace-with") {
+            let (s, path) = try!(val.string(&format!("source.{}.replace-with",
+                                                     name)));
+            replace_with = Some((s.to_string(), path.to_path_buf()));
+        }
+
+        self.add(name, SourceConfig {
+            id: src,
+            replace_with: replace_with,
+        });
+
+        return Ok(());
+
+        fn url(cfg: &ConfigValue, key: &str) -> CargoResult<Url> {
+            let (url, path) = try!(cfg.string(key));
+            url.to_url().chain_error(|| {
+                human(format!("configuration key `{}` specified an invalid \
+                               URL (in {})", key, path.display()))
+
+            })
+        }
+    }
+}
index 7db7361931194cfb1c21cfdf512c8d371f57dfca..53c573aa38c1db7b743ae68d1a746ca58d78f1ce 100644 (file)
@@ -1,7 +1,11 @@
 pub use self::path::PathSource;
 pub use self::git::GitSource;
-pub use self::registry::RegistrySource;
+pub use self::registry::{RegistrySource, CRATES_IO};
+pub use self::replaced::ReplacedSource;
+pub use self::config::SourceConfigMap;
 
 pub mod path;
 pub mod git;
 pub mod registry;
+pub mod config;
+pub mod replaced;
index 0b40e17c50369120f9c2044810ee3423bd9df3ab..460285e41d2f0e235c353f382eac76b5d6c4672d 100644 (file)
@@ -180,8 +180,8 @@ use util::{hex, Sha256, paths, Filesystem, FileLock};
 use util::network;
 use ops;
 
-const DEFAULT: &'static str = "https://github.com/rust-lang/crates.io-index";
 const INDEX_LOCK: &'static str = ".cargo-index-lock";
+pub static CRATES_IO: &'static str = "https://github.com/rust-lang/crates.io-index";
 
 pub struct RegistrySource<'cfg> {
     source_id: SourceId,
@@ -247,21 +247,6 @@ impl<'cfg> RegistrySource<'cfg> {
         }
     }
 
-    /// Get the configured default registry URL.
-    ///
-    /// This is the main cargo registry by default, but it can be overridden in
-    /// a .cargo/config
-    pub fn url(config: &Config) -> CargoResult<Url> {
-        let config = try!(ops::registry_configuration(config));
-        let url = config.index.unwrap_or(DEFAULT.to_string());
-        url.to_url()
-    }
-
-    /// Get the default url for the registry
-    pub fn default_url() -> String {
-        DEFAULT.to_string()
-    }
-
     /// Decode the configuration stored within the registry.
     ///
     /// This requires that the index has been at least checked out.
diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs
new file mode 100644 (file)
index 0000000..cd0ffd4
--- /dev/null
@@ -0,0 +1,55 @@
+use core::{Source, Registry, PackageId, Package, Dependency, Summary, SourceId};
+use util::{CargoResult, ChainError, human};
+
+pub struct ReplacedSource<'cfg> {
+    to_replace: SourceId,
+    replace_with: SourceId,
+    inner: Box<Source + 'cfg>,
+}
+
+impl<'cfg> ReplacedSource<'cfg> {
+    pub fn new(to_replace: &SourceId,
+               replace_with: &SourceId,
+               src: Box<Source + 'cfg>) -> ReplacedSource<'cfg> {
+        ReplacedSource {
+            to_replace: to_replace.clone(),
+            replace_with: replace_with.clone(),
+            inner: src,
+        }
+    }
+}
+
+impl<'cfg> Registry for ReplacedSource<'cfg> {
+    fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
+        let dep = dep.clone().map_source(&self.to_replace, &self.replace_with);
+        let ret = try!(self.inner.query(&dep).chain_error(|| {
+            human(format!("failed to query replaced source `{}`",
+                          self.to_replace))
+        }));
+        Ok(ret.into_iter().map(|summary| {
+            summary.map_source(&self.replace_with, &self.to_replace)
+        }).collect())
+    }
+}
+
+impl<'cfg> Source for ReplacedSource<'cfg> {
+    fn update(&mut self) -> CargoResult<()> {
+        self.inner.update().chain_error(|| {
+            human(format!("failed to update replaced source `{}`",
+                          self.to_replace))
+        })
+    }
+
+    fn download(&mut self, id: &PackageId) -> CargoResult<Package> {
+        let id = id.with_source_id(&self.replace_with);
+        let pkg = try!(self.inner.download(&id).chain_error(|| {
+            human(format!("failed to download replaced source `{}`",
+                          self.to_replace))
+        }));
+        Ok(pkg.map_source(&self.replace_with, &self.to_replace))
+    }
+
+    fn fingerprint(&self, id: &Package) -> CargoResult<String> {
+        self.inner.fingerprint(id)
+    }
+}
index 28d890d76046f6e2362139ab06216858e8c3f51d..43721f016db4aa16b85e3bf03f4091f96c343589 100644 (file)
@@ -274,7 +274,7 @@ impl Config {
     }
 
     pub fn expected<T>(&self, ty: &str, key: &str, val: CV) -> CargoResult<T> {
-        val.expected(ty).map_err(|e| {
+        val.expected(ty, key).map_err(|e| {
             human(format!("invalid configuration for key `{}`\n{}", key, e))
         })
     }
@@ -512,38 +512,39 @@ impl ConfigValue {
         Ok(())
     }
 
-    pub fn i64(&self) -> CargoResult<(i64, &Path)> {
+    pub fn i64(&self, key: &str) -> CargoResult<(i64, &Path)> {
         match *self {
             CV::Integer(i, ref p) => Ok((i, p)),
-            _ => self.expected("integer"),
+            _ => self.expected("integer", key),
         }
     }
 
-    pub fn string(&self) -> CargoResult<(&str, &Path)> {
+    pub fn string(&self, key: &str) -> CargoResult<(&str, &Path)> {
         match *self {
             CV::String(ref s, ref p) => Ok((s, p)),
-            _ => self.expected("string"),
+            _ => self.expected("string", key),
         }
     }
 
-    pub fn table(&self) -> CargoResult<(&HashMap<String, ConfigValue>, &Path)> {
+    pub fn table(&self, key: &str)
+                 -> CargoResult<(&HashMap<String, ConfigValue>, &Path)> {
         match *self {
             CV::Table(ref table, ref p) => Ok((table, p)),
-            _ => self.expected("table"),
+            _ => self.expected("table", key),
         }
     }
 
-    pub fn list(&self) -> CargoResult<&[(String, PathBuf)]> {
+    pub fn list(&self, key: &str) -> CargoResult<&[(String, PathBuf)]> {
         match *self {
             CV::List(ref list, _) => Ok(list),
-            _ => self.expected("list"),
+            _ => self.expected("list", key),
         }
     }
 
-    pub fn boolean(&self) -> CargoResult<(bool, &Path)> {
+    pub fn boolean(&self, key: &str) -> CargoResult<(bool, &Path)> {
         match *self {
             CV::Boolean(b, ref p) => Ok((b, p)),
-            _ => self.expected("bool"),
+            _ => self.expected("bool", key),
         }
     }
 
@@ -567,10 +568,10 @@ impl ConfigValue {
         }
     }
 
-    fn expected<T>(&self, wanted: &str) -> CargoResult<T> {
-        Err(internal(format!("expected a {}, but found a {} in {}",
-                             wanted, self.desc(),
-                             self.definition_path().display())))
+    fn expected<T>(&self, wanted: &str, key: &str) -> CargoResult<T> {
+        Err(human(format!("expected a {}, but found a {} for `{}` in {}",
+                          wanted, self.desc(), key,
+                          self.definition_path().display())))
     }
 
     fn into_toml(self) -> toml::Value {
index cdb3d999ce1662df5e2aa788542a2de2087ee3db..ffc089aa5385b35e8072dee29e6330f63243890c 100644 (file)
@@ -838,7 +838,7 @@ impl TomlDependency {
                     cx.source_id.clone()
                 }
             },
-            (None, None) => try!(SourceId::for_central(cx.config)),
+            (None, None) => try!(SourceId::crates_io(cx.config)),
         };
 
         let version = details.version.as_ref().map(|v| &v[..]);
index 2ccece7d550f73c15b2a4ba0d0701bc7fbe108d1..d7d0192bd16f25eddc23937ec8c70c34341b49a3 100644 (file)
@@ -74,11 +74,12 @@ fn bad3() {
               proxy = true
         "#);
     Package::new("foo", "1.0.0").publish();
+
     assert_that(foo.cargo_process("publish").arg("-v"),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry `[..]`
 [ERROR] invalid configuration for key `http.proxy`
-expected a string, but found a boolean in [..]config
+expected a string, but found a boolean for `http.proxy` in [..]config
 "));
 }
 
@@ -95,7 +96,7 @@ fn bad4() {
 
 Caused by:
   invalid configuration for key `cargo-new.name`
-expected a string, but found a boolean in [..]config
+expected a string, but found a boolean for `cargo-new.name` in [..]config
 "));
 }
 
@@ -538,6 +539,156 @@ This will be considered an error in future versions
 "));
 }
 
+#[test]
+fn bad_source_config1() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.foo]
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: no source URL specified for `source.foo`, needs [..]
+"));
+}
+
+#[test]
+fn bad_source_config2() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.crates-io]
+            registry = 'http://example.com'
+            replace-with = 'bar'
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `bar`
+
+Caused by:
+  Unable to update registry https://[..]
+
+Caused by:
+  could not find a configured source with the name `bar` \
+    when attempting to lookup `crates-io` (configuration in [..])
+"));
+}
+
+#[test]
+fn bad_source_config3() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.crates-io]
+            registry = 'http://example.com'
+            replace-with = 'crates-io'
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `bar`
+
+Caused by:
+  Unable to update registry https://[..]
+
+Caused by:
+  detected a cycle of `replace-with` sources, [..]
+"));
+}
+
+#[test]
+fn bad_source_config4() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.crates-io]
+            registry = 'http://example.com'
+            replace-with = 'bar'
+
+            [source.bar]
+            registry = 'http://example.com'
+            replace-with = 'crates-io'
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `bar`
+
+Caused by:
+  Unable to update registry https://[..]
+
+Caused by:
+  detected a cycle of `replace-with` sources, the source `crates-io` is \
+    eventually replaced with itself (configuration in [..])
+"));
+}
+
+#[test]
+fn bad_source_config5() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.crates-io]
+            registry = 'http://example.com'
+            replace-with = 'bar'
+
+            [source.bar]
+            registry = 'not a url'
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: configuration key `source.bar.registry` specified an invalid URL (in [..])
+
+Caused by:
+  invalid url `not a url`: [..]
+"));
+}
+
 #[test]
 fn both_git_and_path_specified() {
     let foo = project("foo")
@@ -561,6 +712,31 @@ This will be considered an error in future versions
 "));
 }
 
+#[test]
+fn bad_source_config6() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.crates-io]
+            registry = 'http://example.com'
+            replace-with = ['not', 'a', 'string']
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: expected a string, but found a array for `source.crates-io.replace-with` in [..]
+"));
+}
+
 #[test]
 fn ignored_git_revision() {
     let foo = project("foo")
@@ -581,3 +757,56 @@ fn ignored_git_revision() {
 [WARNING] key `branch` is ignored for dependency (bar). \
 This will be considered an error in future versions"));
 }
+
+#[test]
+#[ignore]
+fn bad_source_config7() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.foo]
+            registry = 'http://example.com'
+            directory = 'file:///another/file'
+        "#);
+
+    Package::new("bar", "0.1.0").publish();
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: more than one source URL specified for `source.foo`
+"));
+}
+
+#[test]
+#[ignore]
+fn bad_source_config8() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file(".cargo/config", r#"
+            [source.foo]
+            directory = 'file://another/file'
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+error: failed to convert `file://another/file` to an absolute path (configured in [..])
+"));
+}
index 3cc250af3f1b80f92a818c8f971a09f78473cc00..7814a45a0dd51980e4353024ecdb07dbf1167955 100644 (file)
@@ -2113,7 +2113,7 @@ fn warnings_hidden_for_upstream() {
                        .with_stderr("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] bar v0.1.0 ([..])
-[COMPILING] bar v0.1.0 ([..])
+[COMPILING] bar v0.1.0
 [RUNNING] `rustc [..]`
 [RUNNING] `[..]`
 [RUNNING] `rustc [..]`
@@ -2159,7 +2159,7 @@ fn warnings_printed_on_vv() {
                        .with_stderr("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] bar v0.1.0 ([..])
-[COMPILING] bar v0.1.0 ([..])
+[COMPILING] bar v0.1.0
 [RUNNING] `rustc [..]`
 [RUNNING] `[..]`
 warning: foo
index c026382e4d005c829c6fe1dcfb8393152c4e742c..b235d220f43b00d7d83332603bda3f53c2f39179 100644 (file)
@@ -19,7 +19,7 @@ fn alias_incorrect_config_type() {
                 execs().with_status(101).
                 with_stderr_contains("[ERROR] invalid configuration \
 for key `alias.b-cargo-test`
-expected a list, but found a integer in [..]"));
+expected a list, but found a integer for [..]"));
 }
 
 
index a783c6c0b05f9edbf83959464aeaedf3c398c475..dcf6dc6d30b74237dec694a3d06ba15388e4a3c7 100644 (file)
@@ -45,16 +45,23 @@ fn init() {
     }
     t!(t!(File::create(&config)).write_all(format!(r#"
         [registry]
-            index = "{reg}"
             token = "api-token"
+
+        [source.crates-io]
+        registry = 'https://wut'
+        replace-with = 'dummy-registry'
+
+        [source.dummy-registry]
+        registry = '{reg}'
     "#, reg = registry()).as_bytes()));
 
     // Init a new registry
     repo(&registry_path())
         .file("config.json", &format!(r#"
-            {{"dl":"{}","api":""}}
+            {{"dl":"{0}","api":"{0}"}}
         "#, dl_url()))
         .build();
+    fs::create_dir_all(dl_path().join("api/v1/crates")).unwrap();
 }
 
 impl Package {
index 8a967d1dc766b653f7463e3dbb7cd0f890a781da..52576d5bb237bd11bc5527a25b0929a7f1d99d59 100644 (file)
@@ -36,8 +36,8 @@ fn simple() {
     assert_that(cargo_process("install").arg("foo"),
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `[..]`
-[DOWNLOADING] foo v0.0.1 (registry file://[..])
-[COMPILING] foo v0.0.1 (registry file://[..])
+[DOWNLOADING] foo v0.0.1 (registry [..])
+[COMPILING] foo v0.0.1
 [FINISHED] release [optimized] target(s) in [..]
 [INSTALLING] {home}[..]bin[..]foo[..]
 warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
@@ -63,6 +63,8 @@ fn pick_max_version() {
 [UPDATING] registry `[..]`
 [DOWNLOADING] foo v0.0.2 (registry file://[..])
 [COMPILING] foo v0.0.2 (registry file://[..])
+[DOWNLOADING] foo v0.0.2 (registry [..])
+[COMPILING] foo v0.0.2
 [FINISHED] release [optimized] target(s) in [..]
 [INSTALLING] {home}[..]bin[..]foo[..]
 warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
@@ -77,7 +79,7 @@ fn missing() {
     assert_that(cargo_process("install").arg("bar"),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry [..]
-[ERROR] could not find `bar` in `registry file://[..]`
+[ERROR] could not find `bar` in `registry [..]`
 "));
 }
 
@@ -87,7 +89,7 @@ fn bad_version() {
     assert_that(cargo_process("install").arg("foo").arg("--vers=0.2.0"),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry [..]
-[ERROR] could not find `foo` in `registry file://[..]` with version `0.2.0`
+[ERROR] could not find `foo` in `registry [..]` with version `0.2.0`
 "));
 }
 
@@ -533,7 +535,7 @@ fn compile_failure() {
 
     assert_that(cargo_process("install").arg("--path").arg(p.root()),
                 execs().with_status(101).with_stderr_contains("\
-[ERROR] failed to compile `foo v0.1.0 (file://[..])`, intermediate artifacts can be \
+[ERROR] failed to compile `foo v0.1.0 ([..])`, intermediate artifacts can be \
     found at `[..]target`
 
 Caused by:
@@ -583,9 +585,9 @@ fn list() {
                 execs().with_status(0));
     assert_that(cargo_process("install").arg("--list"),
                 execs().with_status(0).with_stdout("\
-bar v0.2.1 (registry [..]):
+bar v0.2.1:
     bar[..]
-foo v0.0.1 (registry [..]):
+foo v0.0.1:
     foo[..]
 "));
 }
@@ -606,7 +608,7 @@ fn uninstall_bin_does_not_exist() {
                 execs().with_status(0));
     assert_that(cargo_process("uninstall").arg("foo").arg("--bin=bar"),
                 execs().with_status(101).with_stderr("\
-[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1 ([..])`
+[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1`
 "));
 }
 
index 478acf883aba4885f9624aeee9e0db50a135e50c..4d5df0f414fd4430501ac5c70894b875dd16c116 100644 (file)
@@ -75,10 +75,10 @@ fn cargo_metadata_with_deps_and_version() {
             {
                 "dependencies": [],
                 "features": {},
-                "id": "baz 0.0.1 (registry+file:[..])",
+                "id": "baz 0.0.1 (registry+[..])",
                 "manifest_path": "[..]Cargo.toml",
                 "name": "baz",
-                "source": "registry+file:[..]",
+                "source": "registry+[..]",
                 "targets": [
                     {
                         "kind": [
@@ -98,16 +98,16 @@ fn cargo_metadata_with_deps_and_version() {
                         "name": "baz",
                         "optional": false,
                         "req": "^0.0.1",
-                        "source": "registry+file:[..]",
+                        "source": "registry+[..]",
                         "target": null,
                         "uses_default_features": true
                     }
                 ],
                 "features": {},
-                "id": "bar 0.0.1 (registry+file:[..])",
+                "id": "bar 0.0.1 (registry+[..])",
                 "manifest_path": "[..]Cargo.toml",
                 "name": "bar",
-                "source": "registry+file:[..]",
+                "source": "registry+[..]",
                 "targets": [
                     {
                         "kind": [
@@ -127,7 +127,7 @@ fn cargo_metadata_with_deps_and_version() {
                         "name": "bar",
                         "optional": false,
                         "req": "*",
-                        "source": "registry+file:[..]",
+                        "source": "registry+[..]",
                         "target": null,
                         "uses_default_features": true
                     }
@@ -153,19 +153,19 @@ fn cargo_metadata_with_deps_and_version() {
             "nodes": [
                 {
                     "dependencies": [
-                        "bar 0.0.1 (registry+file:[..])"
+                        "bar 0.0.1 (registry+[..])"
                     ],
                     "id": "foo 0.5.0 (path+file:[..]foo)"
                 },
                 {
                     "dependencies": [
-                        "baz 0.0.1 (registry+file:[..])"
+                        "baz 0.0.1 (registry+[..])"
                     ],
-                    "id": "bar 0.0.1 (registry+file:[..])"
+                    "id": "bar 0.0.1 (registry+[..])"
                 },
                 {
                     "dependencies": [],
-                    "id": "baz 0.0.1 (registry+file:[..])"
+                    "id": "baz 0.0.1 (registry+[..])"
                 }
             ],
             "root": "foo 0.5.0 (path+file:[..]foo)"
index a0341ca7d02af75b7df0514f9c96bf5ee63d726c..5eebed0bfa134785a074548213627c07e30934e4 100644 (file)
@@ -3,7 +3,7 @@ extern crate hamcrest;
 
 use cargotest::support::git;
 use cargotest::support::paths;
-use cargotest::support::registry::{registry, Package};
+use cargotest::support::registry::Package;
 use cargotest::support::{execs, project};
 use hamcrest::assert_that;
 
@@ -145,7 +145,7 @@ fn transitive() {
 [UPDATING] git repository `[..]`
 [DOWNLOADING] bar v0.2.0 (registry [..])
 [COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] bar v0.2.0 (registry [..])
+[COMPILING] bar v0.2.0
 [COMPILING] local v0.0.1 (file://[..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
 "));
@@ -343,7 +343,7 @@ fn override_adds_some_deps() {
 [UPDATING] registry `file://[..]`
 [UPDATING] git repository `[..]`
 [DOWNLOADING] foo v0.1.1 (registry [..])
-[COMPILING] foo v0.1.1 (registry [..])
+[COMPILING] foo v0.1.1
 [COMPILING] bar v0.1.0 ([..])
 [COMPILING] local v0.0.1 (file://[..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
@@ -356,7 +356,9 @@ fn override_adds_some_deps() {
                 execs().with_status(0).with_stderr("\
 [UPDATING] git repository `file://[..]`
 "));
-    assert_that(p.cargo("update").arg("-p").arg(&format!("{}#bar", registry())),
+    assert_that(p.cargo("update")
+                 .arg("-p")
+                 .arg("https://github.com/rust-lang/crates.io-index#bar"),
                 execs().with_status(0).with_stderr("\
 [UPDATING] registry `file://[..]`
 "));
@@ -532,8 +534,10 @@ fn multiple_specs() {
 
             [replace]
             "foo:0.1.0" = {{ git = '{0}' }}
-            "{1}#foo:0.1.0" = {{ git = '{0}' }}
-        "#, foo.url(), registry()))
+
+            [replace."https://github.com/rust-lang/crates.io-index#foo:0.1.0"]
+            git = '{0}'
+        "#, foo.url()))
         .file("src/lib.rs", "");
 
     assert_that(p.cargo_process("build"),
@@ -545,7 +549,7 @@ error: overlapping replacement specifications found:
   * [..]
   * [..]
 
-both specifications match: foo v0.1.0 ([..])
+both specifications match: foo v0.1.0
 "));
 }
 
index ad02f97f181964630cd21d990a50ff84bcd00916..6b7b19bb080cb38b5d66c24cab75d3e3ce74cc7e 100644 (file)
@@ -25,13 +25,12 @@ fn upload() -> Url { Url::from_file_path(&*upload_path()).ok().unwrap() }
 
 fn setup() {
     let config = paths::root().join(".cargo/config");
-    fs::create_dir_all(config.parent().unwrap()).unwrap();
-    File::create(&config).unwrap().write_all(&format!(r#"
+    t!(fs::create_dir_all(config.parent().unwrap()));
+    t!(t!(File::create(&config)).write_all(&format!(r#"
         [registry]
-            index = "{reg}"
             token = "api-token"
-    "#, reg = registry()).as_bytes()).unwrap();
-    fs::create_dir_all(&upload_path().join("api/v1/crates")).unwrap();
+    "#).as_bytes()));
+    t!(fs::create_dir_all(&upload_path().join("api/v1/crates")));
 
     repo(&registry_path())
         .file("config.json", &format!(r#"{{
@@ -56,7 +55,8 @@ fn simple() {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    assert_that(p.cargo_process("publish").arg("--no-verify"),
+    assert_that(p.cargo_process("publish").arg("--no-verify")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `{reg}`
 [WARNING] manifest has no documentation, [..]
@@ -110,7 +110,8 @@ fn git_deps() {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    assert_that(p.cargo_process("publish").arg("-v").arg("--no-verify"),
+    assert_that(p.cargo_process("publish").arg("-v").arg("--no-verify")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry [..]
 [ERROR] all dependencies must come from the same source.
@@ -143,7 +144,8 @@ fn path_dependency_no_version() {
         "#)
         .file("bar/src/lib.rs", "");
 
-    assert_that(p.cargo_process("publish"),
+    assert_that(p.cargo_process("publish")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry [..]
 [ERROR] all path dependencies must have a version specified when publishing.
@@ -167,7 +169,8 @@ fn unpublishable_crate() {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    assert_that(p.cargo_process("publish"),
+    assert_that(p.cargo_process("publish")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(101).with_stderr("\
 [ERROR] some crates cannot be published.
 `foo` is marked as unpublishable
@@ -195,7 +198,8 @@ fn dont_publish_dirty() {
 
     let p = project("foo");
     t!(File::create(p.root().join("bar")));
-    assert_that(p.cargo("publish"),
+    assert_that(p.cargo("publish")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry `[..]`
 error: 1 dirty files found in the working directory:
@@ -226,7 +230,8 @@ fn publish_clean() {
         .build();
 
     let p = project("foo");
-    assert_that(p.cargo("publish"),
+    assert_that(p.cargo("publish")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(0));
 }
 
@@ -251,7 +256,8 @@ fn publish_in_sub_repo() {
 
     let p = project("foo");
     t!(File::create(p.root().join("baz")));
-    assert_that(p.cargo("publish").cwd(p.root().join("bar")),
+    assert_that(p.cargo("publish").cwd(p.root().join("bar"))
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(0));
 }
 
@@ -277,7 +283,8 @@ fn publish_when_ignored() {
 
     let p = project("foo");
     t!(File::create(p.root().join("baz")));
-    assert_that(p.cargo("publish"),
+    assert_that(p.cargo("publish")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(0));
 }
 
@@ -301,7 +308,8 @@ fn ignore_when_crate_ignored() {
         .nocommit_file("bar/src/main.rs", "fn main() {}");
     let p = project("foo");
     t!(File::create(p.root().join("bar/baz")));
-    assert_that(p.cargo("publish").cwd(p.root().join("bar")),
+    assert_that(p.cargo("publish").cwd(p.root().join("bar"))
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(0));
 }
 
@@ -324,7 +332,8 @@ fn new_crate_rejected() {
         .nocommit_file("src/main.rs", "fn main() {}");
     let p = project("foo");
     t!(File::create(p.root().join("baz")));
-    assert_that(p.cargo("publish"),
+    assert_that(p.cargo("publish")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(101));
 }
 
@@ -343,7 +352,8 @@ fn dry_run() {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    assert_that(p.cargo_process("publish").arg("--dry-run"),
+    assert_that(p.cargo_process("publish").arg("--dry-run")
+                 .arg("--host").arg(registry().to_string()),
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `{reg}`
 [WARNING] manifest has no documentation, [..]
index 93d61ea6db3eeb2146aa65bdc73b58816b4359e2..60ffdae75b30740d120ca3843c4c7ab46db558c6 100644 (file)
@@ -32,7 +32,7 @@ fn simple() {
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `{reg}`
 [DOWNLOADING] bar v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] bar v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -43,8 +43,8 @@ fn simple() {
     assert_that(p.cargo_process("build"),
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `{reg}`
-[..] bar v0.0.1 (registry file://[..])
-[..] foo v0.0.1 ({dir})
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
         dir = p.url(),
@@ -73,8 +73,8 @@ fn deps() {
 [UPDATING] registry `{reg}`
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
-[COMPILING] baz v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] baz v0.0.1
+[COMPILING] bar v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -102,7 +102,7 @@ fn nonexistent() {
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry [..]
 [ERROR] no matching package named `nonexistent` found (required by `foo`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: >= 0.0.0
 "));
 }
@@ -127,7 +127,7 @@ fn wrong_version() {
     assert_that(p.cargo_process("build"),
                 execs().with_status(101).with_stderr_contains("\
 [ERROR] no matching package named `foo` found (required by `foo`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: >= 1.0.0
 versions found: 0.0.2, 0.0.1
 "));
@@ -138,7 +138,7 @@ versions found: 0.0.2, 0.0.1
     assert_that(p.cargo_process("build"),
                 execs().with_status(101).with_stderr_contains("\
 [ERROR] no matching package named `foo` found (required by `foo`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: >= 1.0.0
 versions found: 0.0.4, 0.0.3, 0.0.2, ...
 "));
@@ -168,6 +168,9 @@ fn bad_cksum() {
 [DOWNLOADING] bad-cksum [..]
 [ERROR] unable to get packages from source
 
+Caused by:
+  failed to download replaced source `registry https://[..]`
+
 Caused by:
   failed to download package `bad-cksum v0.0.1 (registry file://[..])` from [..]
 
@@ -195,7 +198,7 @@ fn update_registry() {
     assert_that(p.cargo_process("build"),
                 execs().with_status(101).with_stderr_contains("\
 [ERROR] no matching package named `notyet` found (required by `foo`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: >= 0.0.0
 "));
 
@@ -205,7 +208,7 @@ version required: >= 0.0.0
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `{reg}`
 [DOWNLOADING] notyet v0.0.1 (registry file://[..])
-[COMPILING] notyet v0.0.1 (registry file://[..])
+[COMPILING] notyet v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -247,7 +250,7 @@ fn package_with_path_deps() {
 
 Caused by:
   no matching package named `notyet` found (required by `foo`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: ^0.0.1
 "));
 
@@ -259,7 +262,7 @@ version required: ^0.0.1
 [VERIFYING] foo v0.0.1 ({dir})
 [UPDATING] registry `[..]`
 [DOWNLOADING] notyet v0.0.1 (registry file://[..])
-[COMPILING] notyet v0.0.1 (registry file://[..])
+[COMPILING] notyet v0.0.1
 [COMPILING] foo v0.0.1 ({dir}[..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ", dir = p.url())));
@@ -286,7 +289,7 @@ fn lockfile_locks() {
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] bar v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] bar v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -322,8 +325,8 @@ fn lockfile_locks_transitively() {
 [UPDATING] registry `[..]`
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
-[COMPILING] baz v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] baz v0.0.1
+[COMPILING] bar v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -362,8 +365,8 @@ fn yanks_are_not_used() {
 [UPDATING] registry `[..]`
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
-[COMPILING] baz v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] baz v0.0.1
+[COMPILING] bar v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -392,7 +395,7 @@ fn relying_on_a_yank_is_bad() {
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr_contains("\
 [ERROR] no matching package named `baz` found (required by `bar`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: = 0.0.2
 versions found: 0.0.1
 "));
@@ -428,7 +431,7 @@ fn yanks_in_lockfiles_are_ok() {
     assert_that(p.cargo("update"),
                 execs().with_status(101).with_stderr_contains("\
 [ERROR] no matching package named `bar` found (required by `foo`)
-location searched: registry file://[..]
+location searched: registry [..]
 version required: *
 "));
 }
@@ -490,14 +493,14 @@ fn update_lockfile() {
                  .arg("-p").arg("bar").arg("--precise").arg("0.0.2"),
                 execs().with_status(0).with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] bar v0.0.1 (registry file://[..]) -> v0.0.2
+[UPDATING] bar v0.0.1 -> v0.0.2
 "));
 
     println!("0.0.2 build");
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stderr(&format!("\
 [DOWNLOADING] [..] v0.0.2 (registry file://[..])
-[COMPILING] bar v0.0.2 (registry file://[..])
+[COMPILING] bar v0.0.2
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -508,14 +511,14 @@ fn update_lockfile() {
                  .arg("-p").arg("bar"),
                 execs().with_status(0).with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] bar v0.0.2 (registry file://[..]) -> v0.0.3
+[UPDATING] bar v0.0.2 -> v0.0.3
 "));
 
     println!("0.0.3 build");
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stderr(&format!("\
 [DOWNLOADING] [..] v0.0.3 (registry file://[..])
-[COMPILING] bar v0.0.3 (registry file://[..])
+[COMPILING] bar v0.0.3
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -528,8 +531,8 @@ fn update_lockfile() {
                 .arg("-p").arg("bar"),
                execs().with_status(0).with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] bar v0.0.3 (registry file://[..]) -> v0.0.4
-[ADDING] spam v0.2.5 (registry file://[..])
+[UPDATING] bar v0.0.3 -> v0.0.4
+[ADDING] spam v0.2.5
 "));
 
    println!("new dependencies update");
@@ -538,8 +541,8 @@ fn update_lockfile() {
                 .arg("-p").arg("bar"),
                execs().with_status(0).with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] bar v0.0.4 (registry file://[..]) -> v0.0.5
-[REMOVING] spam v0.2.5 (registry file://[..])
+[UPDATING] bar v0.0.4 -> v0.0.5
+[REMOVING] spam v0.2.5
 "));
 }
 
@@ -565,7 +568,7 @@ fn dev_dependency_not_used() {
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] [..] v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] bar v0.0.1
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -633,7 +636,7 @@ fn updating_a_dep() {
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] bar v0.0.1 (registry file://[..])
-[COMPILING] bar v0.0.1 (registry file://[..])
+[COMPILING] bar v0.0.1
 [COMPILING] a v0.0.1 ({dir}/a)
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
@@ -656,7 +659,7 @@ fn updating_a_dep() {
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] bar v0.1.0 (registry file://[..])
-[COMPILING] bar v0.1.0 (registry file://[..])
+[COMPILING] bar v0.1.0
 [COMPILING] a v0.0.1 ({dir}/a)
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
@@ -702,7 +705,7 @@ fn git_and_registry_dep() {
 [UPDATING] [..]
 [UPDATING] [..]
 [DOWNLOADING] a v0.0.1 (registry file://[..])
-[COMPILING] a v0.0.1 (registry [..])
+[COMPILING] a v0.0.1
 [COMPILING] b v0.0.1 ([..])
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
@@ -729,9 +732,7 @@ fn update_publish_then_update() {
         "#)
         .file("src/main.rs", "fn main() {}");
     p.build();
-
     Package::new("a", "0.1.0").publish();
-
     assert_that(p.cargo("build"),
                 execs().with_status(0));
 
@@ -749,7 +750,7 @@ fn update_publish_then_update() {
                 execs().with_status(0).with_stderr(&format!("\
 [UPDATING] [..]
 [DOWNLOADING] a v0.1.1 (registry file://[..])
-[COMPILING] a v0.1.1 (registry [..])
+[COMPILING] a v0.1.1
 [COMPILING] foo v0.5.0 ({dir})
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 ",
@@ -809,15 +810,15 @@ fn update_transitive_dependency() {
                 execs().with_status(0)
                        .with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] b v0.1.0 (registry [..]) -> v0.1.1
+[UPDATING] b v0.1.0 -> v0.1.1
 "));
 
     assert_that(p.cargo("build"),
                 execs().with_status(0)
                        .with_stderr("\
 [DOWNLOADING] b v0.1.1 (registry file://[..])
-[COMPILING] b v0.1.1 (registry [..])
-[COMPILING] a v0.1.0 (registry [..])
+[COMPILING] b v0.1.1
+[COMPILING] a v0.1.0
 [COMPILING] foo v0.5.0 ([..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 "));
@@ -892,15 +893,15 @@ fn update_multiple_packages() {
                 execs().with_status(0)
                        .with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] a v0.1.0 (registry [..]) -> v0.1.1
-[UPDATING] b v0.1.0 (registry [..]) -> v0.1.1
+[UPDATING] a v0.1.0 -> v0.1.1
+[UPDATING] b v0.1.0 -> v0.1.1
 "));
 
     assert_that(p.cargo("update").arg("-pb").arg("-pc"),
                 execs().with_status(0)
                        .with_stderr("\
 [UPDATING] registry `[..]`
-[UPDATING] c v0.1.0 (registry [..]) -> v0.1.1
+[UPDATING] c v0.1.0 -> v0.1.1
 "));
 
     assert_that(p.cargo("build"),
@@ -912,11 +913,11 @@ fn update_multiple_packages() {
                        .with_stderr_contains("\
 [DOWNLOADING] c v0.1.1 (registry file://[..])")
                        .with_stderr_contains("\
-[COMPILING] a v0.1.1 (registry [..])")
+[COMPILING] a v0.1.1")
                        .with_stderr_contains("\
-[COMPILING] b v0.1.1 (registry [..])")
+[COMPILING] b v0.1.1")
                        .with_stderr_contains("\
-[COMPILING] c v0.1.1 (registry [..])")
+[COMPILING] c v0.1.1")
                        .with_stderr_contains("\
 [COMPILING] foo v0.5.0 ([..])"));
 }
@@ -1034,7 +1035,7 @@ fn only_download_relevant() {
                 execs().with_status(0).with_stderr("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] baz v0.1.0 ([..])
-[COMPILING] baz v0.1.0 ([..])
+[COMPILING] baz v0.1.0
 [COMPILING] bar v0.5.0 ([..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs
 "));
index 19f04a33bdf81fc2692e7c17b4231d554a9b5cd7..b2f1c8ad1bcb3f947e8a3deeae84053e128027bd 100644 (file)
@@ -22,10 +22,6 @@ fn api() -> Url { Url::from_file_path(&*api_path()).ok().unwrap() }
 fn setup() {
     let config = paths::root().join(".cargo/config");
     fs::create_dir_all(config.parent().unwrap()).unwrap();
-    File::create(&config).unwrap().write_all(format!(r#"
-        [registry]
-            index = "{reg}"
-    "#, reg = registry()).as_bytes()).unwrap();
     fs::create_dir_all(&api_path().join("api/v1")).unwrap();
 
     repo(&registry_path())
@@ -85,7 +81,8 @@ fn simple() {
              .write_all(contents.as_bytes()).unwrap();
     }
 
-    assert_that(cargo_process("search").arg("postgres"),
+    assert_that(cargo_process("search").arg("postgres")
+                    .arg("--host").arg(registry().to_string()),
                 execs().with_status(0)
                        .with_stderr("\
 [UPDATING] registry `[..]`")
@@ -136,7 +133,8 @@ fn multiple_query_params() {
              .write_all(contents.as_bytes()).unwrap();
     }
 
-    assert_that(cargo_process("search").arg("postgres").arg("sql"),
+    assert_that(cargo_process("search").arg("postgres").arg("sql")
+                    .arg("--host").arg(registry().to_string()),
                 execs().with_status(0)
                        .with_stderr("\
 [UPDATING] registry `[..]`")
index dcec77ae3f4ef47a1857736bfd45ab67d3b55a57..8ded09b772a98fec4e537178243dc2efbf4cd419 100644 (file)
@@ -502,7 +502,7 @@ fn share_dependencies() {
                        .with_stderr("\
 [UPDATING] registry `[..]`
 [DOWNLOADING] dep1 v0.1.3 ([..])
-[COMPILING] dep1 v0.1.3 ([..])
+[COMPILING] dep1 v0.1.3
 [COMPILING] foo v0.1.0 ([..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
 "));
@@ -587,7 +587,7 @@ fn lock_works_for_everyone() {
                 execs().with_status(0)
                        .with_stderr("\
 [DOWNLOADING] dep2 v0.1.0 ([..])
-[COMPILING] dep2 v0.1.0 ([..])
+[COMPILING] dep2 v0.1.0
 [COMPILING] foo v0.1.0 ([..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
 "));
@@ -596,7 +596,7 @@ fn lock_works_for_everyone() {
                 execs().with_status(0)
                        .with_stderr("\
 [DOWNLOADING] dep1 v0.1.0 ([..])
-[COMPILING] dep1 v0.1.0 ([..])
+[COMPILING] dep1 v0.1.0
 [COMPILING] bar v0.1.0 ([..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
 "));